﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using static System.Runtime.InteropServices.JavaScript.JSType;

namespace demo01动态数组
{
    //泛型：泛指某种类型

    //类：类 继承
    //类： 接口 实现
    //让动态数组更加通用 可以存放任何数据类型
    public class MyArraylist<E> : ListInterface<E>
    {
        //保存元素 的数量
        private int size;
            
        //保存所有的元素
        private E[] elements;

        private  const int DEFAULT_CAPACITY = 10;

        private const int ELEMENT_NOT_FOUND = -1;

        public MyArraylist(int capaticy)
        {
             capaticy = (capaticy < DEFAULT_CAPACITY) ? DEFAULT_CAPACITY : capaticy;             
             elements=new E[capaticy];
        }

        public MyArraylist() : this(DEFAULT_CAPACITY)
        {

        }


        //位运算
        public void add(E element)
        {

            //elements[size] = element;
            //size++;
            add(size,element);
        }


        public void add(int index, E element)
        {
            rangCheckForAdd(index);

            ensureCapacoty(size+1);

            for (int i = size-1; i >=index; i--)
            {
                elements[i+1]= elements[i];
            }

            elements[index] = element;
            size++;
        }

        /// <summary>
        /// 保证capacity容量
        /// </summary>
        /// <param name="capacity"></param>
        private  void ensureCapacoty(int capacity)
        {
            //获取旧的容量
            int oldCapacity = elements.Length;
            //如果老的容量大于 新的容量方法就不要走了
            if (oldCapacity>= capacity)
            {
                return;
            }
            //>>：左移 1* 1.5
            //《《 右移 /
            //(oldCapacity >> 1) *1.5                                          
            int newCapacity = oldCapacity + (oldCapacity >> 1);

            E[] newElemets = new E[newCapacity];
            for (int i = 0; i < size; i++)
            {
                newElemets[i] = elements[i];
            }
            elements = newElemets;
            Console.WriteLine("扩容"+oldCapacity+"_"+newCapacity);
        }


        /// <summary>
        /// 抛出异常方法
        /// </summary>
        /// <exception cref="IndexOutOfRangeException"></exception>
        private void outOfBounds(int index)
        {
            throw new IndexOutOfRangeException($"Index:={index},Size={size}");
        }

        /// <summary>
        /// 检查索引
        /// </summary>
        /// <param name="index"></param>
        private void rangCheck(int index)
        {
            if (index < 0 || index >= size) 
            {
                outOfBounds(index);
            }

        }

        /// <summary>
        /// 检查索引
        /// </summary>
        /// <param name="index"></param>
        private void rangCheckForAdd(int index)
        {

            if (index < 0 || index > size) 
            {
                outOfBounds(index);
            }

        }


        //index 索引  下标
        public E remove(int index)
        {
            rangCheck(index);

            E old = elements[index];

            for (int i = index+1; i <= size-1; i++)
            {
                elements[i-1]= elements[i];
            }
            size--;
            return old;
        }


        public void clear()
        {
            size = 0;
           // elements = null;
           
        }


        public bool Contains(E element)
        {

        return  indexOf(element) != ELEMENT_NOT_FOUND;

        }


        public E get(int index)
        {
            rangCheck(index);

            return elements[index];
        }

        public int indexOf(E element)
        {
            for (int i = 0; i < size; i++)
            {
                if (elements[i].Equals(element))
                {
                    return i;
                }
            }
            return ELEMENT_NOT_FOUND;
        }

        public bool isEmpty()
        {
            return size==0;
        }

        public E set(int index, E element)
        {
            rangCheck(index);
            E old = elements[index];
            elements[index]= element;
            return old;
        }

        public int Size()
        {
            return size;
        }

        public override string ToString()
        {
            string str = "";
            for (int i = 0; i < size; i++)
            {
                str += elements[i];
                if (i!=size-1)
                {
                    str += ",";
                }
            }
            return str;
        }

        
    }



}
